package com.tianji.learning.handle;

import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.tianji.learning.constants.LearningConstants.POINTS_BOARD_TABLE_PREFIX;
import static com.tianji.learning.constants.RedisConstants.POINTS_BOARD_KEY_PREFIX;

@Component
@RequiredArgsConstructor
public class PointsBoardPersistentHandler {

    private final IPointsBoardSeasonService seasonService;

    private final IPointsBoardService pointsBoardService;

    private  final StringRedisTemplate redisTemplate;

//    @Scheduled(cron = "0 0 3 1 * ?") // 每月1号，凌晨3点执行
    /**
     * 创建表
     */
    @XxlJob("createTableJob")
    public void createPointsBoardTableOfLastSeason(){
        //上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);

        Integer season = seasonService.querySeasonByTime(time);
        if (season == null) {
            // 赛季不存在
            return;
        }
        //为了把上月的积分榜数据，持久化到数据库，先创建新表
        pointsBoardService.createPointsBoardTableBySeason(season);
    }

    /**
     * 保存新表到数据库
     */
    public void saveOldBoard2Db(){
        LocalDateTime lastMonth = LocalDateTime.now().minusMonths(1);

        //先查赛季id
        Integer seasonId = seasonService.querySeasonByTime(lastMonth);
        if(ObjectUtils.isEmpty(seasonId) || seasonId==null){
            throw new BizIllegalException("赛季不存在");
        }

        //赛季拼接新表名
        String newTableName=POINTS_BOARD_TABLE_PREFIX+seasonId;
        String key=POINTS_BOARD_KEY_PREFIX+lastMonth.format(DateUtils.POINTS_DATE_SUFFIX_FORMATTER);
        TableInfoContext.setInfo(newTableName);

        //去redis查，分页查是因为可能一次查不完
        //获取当前执行任务的分片编号，从0开始
        int index = XxlJobHelper.getShardIndex();
        int total = XxlJobHelper.getShardTotal();


        int pageNo=index+1;
        int pageSize=1000;
        while(true){
            List<PointsBoard> dataMsg=   pointsBoardService.findCurrentSeasonBoardMsg(Integer.valueOf(pageNo),Integer.valueOf(pageSize),key);
            if(ObjectUtils.isEmpty(dataMsg)){
                break;
            }

            dataMsg.forEach(pointsBoard -> {
                pointsBoard.setId(Long.valueOf(pointsBoard.getRank()));
                pointsBoard.setRank(null);
            });

            //批量保存
            pointsBoardService.saveBatch(dataMsg);

            pageNo+=total;
        }

        TableInfoContext.remove();

    }

    //写完后删除redis
    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis() throws InterruptedException {
        //延迟双写，保持数据一致性
        Thread.sleep(10000);

        LocalDateTime time = LocalDateTime.now().minusMonths(1);

        String key = POINTS_BOARD_KEY_PREFIX + time.format(DateUtils.POINTS_DATE_SUFFIX_FORMATTER);

        redisTemplate.unlink(key);
    }
}